import { i18n, nmAppErrorLog } from '@/common/utils';
import { Form, FormInstance, InputNumber, Table, TableProps } from 'antd';
import { createContext, useContext, useEffect, useRef, useState } from 'react';
import './style.scss';

export interface IQualityItem {
  criteria: string;
  compare: string; // < > = etc.
  value: number;
}

type IDataSource = IQualityItem & {
  key: string;
};

export const MyTable = ({
  data,
  onItemChange,
  onItemSelected,
}: {
  data: IQualityItem[];
  onItemChange: (
    index: number,
    item: IQualityItem,
    isSelected?: boolean,
  ) => void;
  onItemSelected(items: IQualityItem[]);
}) => {
  const [dataSource, setDataSource] = useState<IDataSource[]>([]);
  const [currentSelectedRows, setCurrentSelectedRows] = useState<
    IQualityItem[]
  >([]);

  useEffect(() => {
    setDataSource(data.map((item) => ({ ...item, key: item.criteria })));
  }, [data]);

  const EditableContext = createContext<FormInstance | null>(null);

  const EditableRow: React.FC = ({ ...props }) => {
    const [form] = Form.useForm();
    return (
      <Form
        form={form}
        component={false}>
        <EditableContext.Provider value={form}>
          <tr {...props} />
        </EditableContext.Provider>
      </Form>
    );
  };

  interface EditableCellProps {
    title: React.ReactNode;
    editable: boolean;
    dataIndex: keyof IQualityItem;
    record: IQualityItem;
    handleSave: (record: IQualityItem) => void;
  }

  const EditableCell: React.FC<React.PropsWithChildren<EditableCellProps>> = ({
    title,
    editable,
    children,
    dataIndex,
    record,
    handleSave,
    ...restProps
  }) => {
    const [editing, setEditing] = useState(false);
    const inputRef = useRef<HTMLInputElement>(null);
    const form = useContext(EditableContext)!;

    useEffect(() => {
      if (editing) {
        inputRef.current?.focus();
      }
    }, [editing]);

    const toggleEdit = () => {
      setEditing(!editing);
      form.setFieldsValue({ [dataIndex]: record[dataIndex] });
    };

    const save = async () => {
      try {
        const values = await form.validateFields();

        toggleEdit();
        handleSave({ ...record, ...values });
      } catch (errInfo) {
        nmAppErrorLog('Save failed:', errInfo);
      }
    };

    let childNode = children;

    if (editable) {
      childNode = editing ? (
        <Form.Item
          style={{ margin: 0 }}
          name={dataIndex}
          rules={[
            {
              required: true,
              message: `${title} is required.`,
            },
          ]}>
          <InputNumber
            ref={inputRef}
            onPressEnter={save}
            onBlur={save}
            size='small'
          />
        </Form.Item>
      ) : (
        <div
          className='editable-cell-value-wrap'
          style={{ paddingInlineEnd: 24 }}
          onClick={toggleEdit}>
          {children}
        </div>
      );
    }

    return <td {...restProps}>{childNode}</td>;
  };

  type ColumnTypes = Exclude<TableProps<IQualityItem>['columns'], undefined>;
  const tableColumns: ColumnTypes[number] &
    {
      key: string;
      title: React.ReactNode;
      editable?: boolean;
      dataIndex: string;
      width?: number;
    }[] = [
    {
      title: i18n.t('criteria'),
      dataIndex: 'criteria',
      key: 'criteria',
    },
    {
      title: i18n.t('compare'),
      dataIndex: 'compare',
      key: 'compare',
      width: 80,
    },
    {
      title: i18n.t('value'),
      dataIndex: 'value',
      key: 'value',
      editable: true,
      width: 120,
    },
  ];

  const handleSave = (row: IQualityItem) => {
    const index = dataSource.findIndex(
      (item) => row.criteria === item.criteria,
    );
    const item = dataSource[index];
    // row和item的value相同，则不进行更新
    if (row.value === item.value) {
      return;
    }
    const newData = [...dataSource];
    newData[index] = {
      ...item,
      ...row,
    };
    setDataSource(newData);
    onItemChange(
      index,
      row,
      currentSelectedRows.some((item) => item.criteria === row.criteria),
    );
  };

  const components = {
    body: {
      row: EditableRow,
      cell: EditableCell,
    },
  };
  const columns = tableColumns.map((col) => {
    if (!col.editable) {
      return col;
    }
    return {
      ...col,
      onCell: (record: IQualityItem) => ({
        record,
        editable: col.editable,
        dataIndex: col.dataIndex,
        title: col.title,
        handleSave,
      }),
    };
  });
  const rowSelection: TableProps<IQualityItem>['rowSelection'] = {
    type: 'radio',
    onChange: async (_: React.Key[], selectedRows: IQualityItem[]) => {
      onItemSelected(selectedRows);
      setCurrentSelectedRows(selectedRows);
    },
  };

  return (
    <Table
      style={{ width: '400px', height: '450px', overflow: 'auto' }}
      columns={columns as ColumnTypes}
      dataSource={dataSource}
      pagination={false}
      rowSelection={rowSelection}
      components={components}
      rowClassName={() => 'editable-row'}
      size='middle'
    />
  );
};
